package com.lwq.lwqmicoservice.framework.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.exceptions.ApiException;
import com.lwq.lwqmicoservice.common.exception.FieldException;
import com.lwq.lwqmicoservice.common.model.Dto;
import com.lwq.lwqmicoservice.common.model.SysDict;
import com.lwq.lwqmicoservice.common.model.SysDictDetail;
import com.lwq.lwqmicoservice.common.util.BeanAssistant;
import com.lwq.lwqmicoservice.common.util.StringUtils;
import com.lwq.lwqmicoservice.framework.mapper.DictDetailMapper;
import com.lwq.lwqmicoservice.framework.mapper.DictMapper;
import com.lwq.lwqmicoservice.framework.util.CacheUtil;
import com.lwq.lwqmicoservice.framework.util.RedisUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Description:
 * Author: LiuWenQing
 * Datetime: 2021/6/10
 */
@Service
public class DictService {

    @Autowired
    private DictMapper mapper;
    @Autowired
    private DictDetailMapper dictDetailMapper;
    @Autowired
    private RedisUtil redis;

    public List<SysDict> queryList(Dto dto){
        List<SysDict> dictList = dto == null? mapper.selectList(new QueryWrapper<SysDict>().eq("disabled", SysDict.ENABLE)):
                                mapper.selectByMap(dto);
        dictList.sort(new Comparator<SysDict>() {
            @Override
            public int compare(SysDict o1, SysDict o2) {
                return o1.getSort().compareTo(o2.getSort());
            }
        });
        for (SysDict dict : dictList){
            dict.setDetails(dictDetailMapper.selectList(new QueryWrapper<SysDictDetail>().eq("dict_id", dict.getId()).eq("disabled", SysDict.ENABLE).orderByAsc("sort")));
        }
        return dictList;
    }

    public List<SysDict> findDictByCode(String code, String exclude){
        List<SysDict> list = redis.getCacheList("dict",SysDict.class).stream().filter(e -> e.getCode().equals(code)).collect(Collectors.toList());
        if(StringUtils.isNotEmpty(exclude) && !list.isEmpty() && list.get(0).getDetails().size()>0){
            list.get(0).setDetails(list.get(0).getDetails().stream().filter(e -> !Arrays.asList(exclude.split(",")).contains(e.getName())).collect(Collectors.toList()));
            Collections.sort(list.get(0).getDetails(), new Comparator<SysDictDetail>() {
                @Override
                public int compare(SysDictDetail o1, SysDictDetail o2) {
                    return o1.getSort().compareTo(o2.getSort());
                }
            });
        };
        return list;
    }

    public List<SysDict> queryListCache(){
        return redis.getCacheList("dict",SysDict.class);
    }

    public List<SysDictDetail> queryDictList(Dto dto){
        if(dto == null){
            return dictDetailMapper.selectList(new QueryWrapper<SysDictDetail>()
                    .eq(SysDictDetail.DICT_ID, Long.parseLong(dto.get(SysDictDetail.DICT_ID).toString())).orderByAsc("sort"));
        }else{
            List<SysDictDetail> list = dictDetailMapper.selectByMap(dto);
            list.sort(new Comparator<SysDictDetail>() {
                @Override
                public int compare(SysDictDetail o1, SysDictDetail o2) {
                    return o1.getSort().compareTo(o2.getSort());
                }
            });
            return list;
        }
    }

    public void addDict(SysDict dict) {
        if(mapper.selectOne(new QueryWrapper<SysDict>()
                .eq(SysDict.CODE,dict.getCode()))!= null){
            throw new ApiException("字典编号重复");
        }
        mapper.insert(dict);
    }

    public void addDictDetail(SysDictDetail sysDictDetail){
        if(dictDetailMapper.selectOne(new QueryWrapper<SysDictDetail>()
                .eq(SysDictDetail.NAME, sysDictDetail.getName()).eq("dict_id",sysDictDetail.getDictId()))!= null){
            throw new ApiException("字典明细编号重复");
        }
        dictDetailMapper.insert(sysDictDetail);
    }

    public void editDict(SysDict dict) {
        if(dict.getId() == null){
            throw new FieldException("id不可为空");
        }
        SysDict model = mapper.selectById(dict.getId());
        if(!dict.getCode().equals(model.getCode()) &&
                mapper.selectOne(new QueryWrapper<SysDict>().eq(SysDict.CODE, dict.getCode())) != null){
            throw new ApiException("字典编号重复");
        }
        BeanUtils.copyProperties(dict, model, BeanAssistant.getNullPropertyNames(dict));
        mapper.updateById(model);
    }

    public void editDictDetail(SysDictDetail dictDetail){
        if(dictDetail.getId() == null){
            throw new FieldException("id不可为空");
        }
        SysDictDetail model = dictDetailMapper.selectById(dictDetail.getId());
        if(!dictDetail.getName().equals(model.getName()) &&
                dictDetailMapper.selectOne(new QueryWrapper<SysDictDetail>().eq(SysDictDetail.NAME, dictDetail.getName())) != null){
            throw new ApiException("字典明细编号重复");
        }
        BeanUtils.copyProperties(dictDetail, model, BeanAssistant.getNullPropertyNames(dictDetail));
        dictDetailMapper.updateById(dictDetail);
    }

    @Transactional(rollbackFor = Exception.class)
    public void delDict(Long id){
        List<SysDictDetail> dictDetailList = dictDetailMapper.selectList(new QueryWrapper<SysDictDetail>().eq(SysDictDetail.DICT_ID, id));
        if(!dictDetailList.isEmpty()){
            dictDetailMapper.deleteBatchIds(dictDetailList.stream().
                    map(e->e.getId()).collect(Collectors.toList()));
        }
        mapper.deleteById(id);
    }

    public void delDictDetail(Long id){
        dictDetailMapper.deleteById(id);
    }

    public List<SysDict> refresh(){
        List<SysDict> list = queryList(null);
        redis.setCacheList("dict", list);
        CacheUtil.list = list;
        return list;
    }
}
